/** 
 * \file   Logging.cpp
 * \author T. M. Jandreu
 * 
 * \date December 16, 2012, 10:34 AM
 * 
 * This file contains the function definitions for class Logging
 */

#include "Logging.h"

#include <boost/lexical_cast.hpp>
#include <iostream>
#include <string>
#include <ace/OS_NS_stdlib.h>
#include <ace/OS_NS_sys_time.h>

namespace UTIL {

    Logging::Logging() : outputDir("./"), sequence(0) {
        ACE_LOG_MSG->msg_callback(this);
        ACE_LOG_MSG->set_flags(ACE_Log_Msg::MSG_CALLBACK);
        openLogs();
    }

    Logging::~Logging() {
        closeLogs();
        ACE_LOG_MSG->clr_flags(ACE_Log_Msg::MSG_CALLBACK);
    }

    void Logging::rotateLogs() {
        closeLogs();
        sequence++;
        openLogs();
    }

    std::string Logging::generateFilename(std::string suffix) {
        std::string path = outputDir + ACE_OS::getprogname();
        std::string num;
        try {
            num = boost::lexical_cast< std::string > (sequence);
        } catch (const boost::bad_lexical_cast &e) {
            ERROR("Bad Lexical Cast %s\n", e.what());
        }

        std::string res = path + "." + num + "." + suffix;
        return res;
    }

    void Logging::openLogs() {
        // need to construct the series mask
        fileMap[ LM_INFO ] = new Files(generateFilename("log"));
        fileMap[ LM_DEBUG ] = new Files(generateFilename("debug"));
        fileMap[ LM_ERROR ] = new Files(generateFilename("error"));

        std::string prog = ACE_OS::getprogname();
        ERROR("Opening Error Log for %s\n", prog.c_str());
        DEBUG("Opening Debug Log for %s\n", prog.c_str());
        INFO("Opening Info Log for %s\n", prog.c_str());
    }

    void Logging::closeLogs() {

        std::string prog = ACE_OS::getprogname();
        ERROR("Closing Error Log for %s\n", prog.c_str());
        DEBUG("Closing Debug Log for %s\n", prog.c_str());
        INFO("Closing Info Log for %s\n", prog.c_str());

        // iterate through the map and reset who is still open
        std::map< unsigned long, Files *>::iterator it;
        for (it = fileMap.begin(); it != fileMap.end(); it++) {
            if (it->second) {
                delete it->second;
            }
        }
    }

    void Logging::setOutputDirectory(std::string& outputDir_) {
        if (outputDir.compare(outputDir_.c_str()) != 0) {
            // if the new output dir is different than the old one, cycle the logs
            closeLogs();
            openLogs();
        }
    }

    void Logging::log(ACE_Log_Record& logRecord) {

        unsigned long msgSeverity = logRecord.type();
        ACE_Log_Priority priority = static_cast<ACE_Log_Priority> (msgSeverity);

        logRecord.dump();

        std::map< unsigned long, Files* >::iterator it = fileMap.find(priority);
        if (it == fileMap.end()) {
            ERROR("File %d not found in fileMap\n", priority);
        } else {
            // write the log record to the file
            it->second->write(logRecord.msg_data());
        }

    }

} // namespace UTIL
